(function($) {
    
	if (typeof($) === 'undefined' || typeof($.ui) === 'undefined') {
		throw 'Requires jQuery and jQuery UI';
	}

    jqkit.components.Button = function(element) {
	    var self = this;
        
		if (jqkit.isDefinedAndNotNull(element) === false) {
			throw 'Html element parameter is not defined';
		}
		
		if (element instanceof $ === false) {
			element = $(element);
		}
		
		if (element.hasClass('vc-btn') === false) {
			throw 'Html element parameter is not a valid button component wrapper.';
		}

        self.wrapper_ = element;
        self.type_ = self.wrapper_.attr('data-type');
        self.allowSecondaryEvent_ = (
            self.type_ === jqkit.components.Button.types.SPLIT_BUTTON ||
            self.type_ === jqkit.components.Button.types.SPLIT_LINK_BUTTON ||
            self.type_ === jqkit.components.Button.types.SPLIT_INPUT_BUTTON
        );

        self.wrapper_.data('jqkit.components.button', self);
    };

    jqkit.components.Button.types = {
        DEFAULT: '0',
        LINK_BUTTON: '1',
        INPUT_BUTTON: '2',
        DROP_DOWN_BUTTON: '3',
        SPLIT_BUTTON: '4',
        SPLIT_LINK_BUTTON: '5',
        SPLIT_INPUT_BUTTON: '6'
    };

    jqkit.components.Button.prototype.wrapper_;

    jqkit.components.Button.prototype.type_;

    jqkit.components.Button.prototype.allowSecondaryEvent_;

    jqkit.components.Button.prototype.isEnabled = function() {
        return !this.wrapper_.hasClass('vc-btn-disabled');
    };

    jqkit.components.Button.prototype.isActive = function() {
        return this.wrapper_.hasClass('vc-btn-active');
    };

    jqkit.components.Button.prototype.isMenuVisible = function() {
        var self = this;
        return (
            (self.allowSecondaryEvent_ === true || self.type_ === jqkit.components.Button.types.DROP_DOWN_BUTTON) && 
            (self.wrapper_.children('.vc-btn-menu').length === 0)
        );
    };

    jqkit.components.Button.prototype.enable = function() {
        this.wrapper_.removeClass('vc-btn-disabled');
    };

    jqkit.components.Button.prototype.disable = function() {
        var self = this;
        self.wrapper_.addClass('vc-btn-disabled');
        if (self.isMenuVisible() === true) {
            jqkit.components.Button.hideActiveMenu();
        }
    };

    jqkit.components.Button.prototype.triggerPrimaryAction = function() {
        var self = this;

        if (self.isEnabled() === false) {
            return;
        }

        // Trigger optional primary action handler.
        var onBeforePrimaryAction = self.wrapper_.attr('data-before-action');
        if (typeof(onBeforePrimaryAction) !== 'undefined') {
            if (jqkit.executeByName.call(self.wrapper_, onBeforePrimaryAction) === false) {
                return;
            }
        }

        if (self.type_ === jqkit.components.Button.types.LINK_BUTTON || self.type_ === jqkit.components.Button.types.SPLIT_LINK_BUTTON) {
            // Link button.
            // Note: FF does not support trigger <a> clicks via javascript.
            var anchor = self.wrapper_.children('a');
            var url = anchor.attr('href') || '';
            if (url.length > 1 && url.substring(0, 1) === '#') {
                // Internal page link.
                $(document).scrollTop($('a[name=' + url.substring(1) + ']').offset().top);
            } else {
                // External page link.
                window.open(url, (anchor.attr('target') || '_self'));
            }
            anchor = null;
        } else if (self.type_ === jqkit.components.Button.types.INPUT_BUTTON || self.type_ === jqkit.components.Button.types.SPLIT_INPUT_BUTTON) {
            // Submit button.
            self.wrapper_.children('input').trigger('click');
        } else if (self.type_ === jqkit.components.Button.types.DROP_DOWN_BUTTON) {
            // Drop down button.
            self.toggleMenu_();
        } else {
            // Default button (do nothing).
        }
    };

    jqkit.components.Button.prototype.triggerSecondaryAction = function() {
        var self = this;
        if (self.isEnabled() === false || self.allowSecondaryEvent_ === false) {
            return;
        }
        self.toggleMenu_();
    };

    jqkit.components.Button.prototype.toggleMenu_ = function(opt_show) {
        var self = this;

        if (self.isEnabled() === false) {
            return;
        }

        // Hide possible open menu for other button.
        if ($('body > div.vc-btn-menu[data-vc-id!=' + self.wrapper_.attr('data-vc-id') + ']').length === 1) {
            if (jqkit.components.Button.hideActiveMenu() === false) {
                // Do nothing.
                return;
            }
        }

        if (jqkit.isDefinedAndNotNull(opt_show) === false) {
            opt_show = !self.isMenuVisible();
        }

        if (self.isMenuVisible() === opt_show) {
            // Do nothing.
            return;
        }

        // Toggle menu.
        if (opt_show === true) {
            // Trigger optional event handler.
            var onBeforeMenuShow = self.wrapper_.attr('data-before-show-menu');
            if (typeof(onBeforeMenuShow) !== 'undefined') {
                if (jqkit.executeByName.call(self.wrapper_, onBeforeMenuShow) === false) {
                    return;
                }
            }

            // Bind global hide event.
            $('html').bind('click.vc_button', function(event) {
                jqkit.components.Button.hideActiveMenu();
            });
            
            self.wrapper_.addClass('vc-btn-active');

            // Show menu.
            var menu = self.wrapper_.children('.vc-btn-menu').remove();
            $('body').append(menu);
            menu.bind('click', function(event) {
                event.stopPropagation();
            }).css({ top:-999, left:-999, position:'absolute', zIndex:999 }).show().position({
                of: self.wrapper_,
                my: 'left top',
                at: 'left bottom'
            });
            menu = null;
        } else {
            // Hide menu.
            jqkit.components.Button.hideActiveMenu();
        }
    };
    
    jqkit.components.Button.initialize = function() {
        $('body').delegate('.vc-btn', 'keypress click', function(event) {
            // Don't handle event if triggered from a native link or input tag from within the component.
            if (event.target.tagName.toLowerCase() === 'a' || event.target.tagName.toLowerCase() === 'input') {
                return;
            }
            // If keypress event, verify its an enter key.
            if (event.type === 'keypress' && event.keyCode !== 13) {
                return;
            }
            var btnElem = $(this), btn = btnElem.data('jqkit.components.button');
            // Make sure button is initialized.
            if (typeof(btn) === 'undefined') {
                btn = new jqkit.components.Button(btnElem);
            }
            // Trigger button action.
            if (btn.allowSecondaryEvent_ === true && $(event.target).closest('.vc-btn, .vc-btn-secondary').hasClass('vc-btn-secondary') === true) {
                // Secondary click.
                btn.triggerSecondaryAction();
            } else {
                // Primary click.
                btn.triggerPrimaryAction();
            }
            // Prevent further propagation.
            event.stopPropagation();
        });
    };
    
    jqkit.components.Button.hideActiveMenu = function() {
        var menu = $('body > div.vc-btn-menu');

        // Is a menu active? If not, make sure not hide event is bound.
        if (menu.length === 0) {
            $('html').unbind('click.vc_button');
            return;
        }

        var btn = $('div.vc-btn[data-vc-id=' + menu.attr('data-vc-id') + ']').data('jqkit.components.button');
        
        if (jqkit.isDefinedAndNotNull(btn) === true) {
            // Trigger optional event handler.
            var onBeforeMenuHide = btn.wrapper_.attr('data-before-hide-menu');
            if (typeof(onBeforeMenuHide) !== 'undefined') {
                if (jqkit.executeByName.call(btn.wrapper_, onBeforeMenuHide) === false) {
                    return false;
                }
            }
        }

        $('html').unbind('click.vc_button');
        menu.remove().hide();
        btn.wrapper_.removeClass('vc-btn-active').append(menu);
        menu = null;
        btn = null;
    };

    $(document).ready(function() {
        jqkit.components.Button.initialize();
    });

})(jQuery);